﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;


namespace NOS.Security
{
    public class AssemblyCache
    {
        public AssemblyCache(string ServiceName, string AssemblyPath, Assembly LoadedAssembly)
        {
            this.ServiceName = ServiceName;
            this.AssemblyPath = AssemblyPath;
            this.LoadedAssembly = LoadedAssembly;
        }

        public string ServiceName{ get; set; }

        public string AssemblyPath { get; set; }

        public Assembly LoadedAssembly { get; set; }               
    }

    public class InstanceCache
    {
        private object _Instance = null;
        public DateTime Lastaccess = DateTime.Now;

        public InstanceCache(object Instance)
        {         
            _Instance = Instance;
        }

        public object Instance { 
            get
            {
                Lastaccess = DateTime.Now;
                return _Instance;
            } 
            set
            {
                Lastaccess = DateTime.Now;
                _Instance = value;
            } 
        }        
    }
    
    public class SafetyHashTable
    {
        #region . Variables .

        private Hashtable Hash = null;
        private int AcessCount = 0;
        private int ReadWaiter = 0;
        private int ExclWaiter = 0;

        #endregion

        public Hashtable HashTable
        {
            get { return Hash; }
        }

        public SafetyHashTable()
        {
            Trace.WriteLine("SafetyHashTable : Creating Instance");
            Hash = new Hashtable();
            Trace.WriteLine("SafetyHashTable: Instance criated");
        }

        public void GetExclusive()
        {
            Trace.WriteLine("SafetyHashTable: Exclusive access required");
            lock (Hash)
            {
                ExclWaiter++;
                if(AcessCount != 0)
                {
                    Trace.WriteLine("SafetyHashTable: Waiting for exclusive access");
                    Monitor.Wait(Hash);
                }
                ExclWaiter--;
                AcessCount = -1;
                Trace.WriteLine("SafetyHashTable: Exclusive acess Allowed");
            }
        }

        public void GetShared()
        {
            Trace.WriteLine("SafetyHashTable: Shared access required");
            lock (Hash)
            {
                ReadWaiter++;
                if (AcessCount < 0 || ExclWaiter > 0)
                {
                    Trace.WriteLine("SafetyHashTable: Waiting for Shared access");
                    Monitor.Wait(Hash);
                }
                ReadWaiter--;
                AcessCount++;
                Trace.WriteLine("SafetyHashTable: Shared access Allowed");
            }
        }

        public void ReleaseExclusive()
        {
            Trace.WriteLine("SafetyHashTable: Realeasing exlusive");        
            lock (Hash)
            {
                AcessCount = 0;
                if (ReadWaiter > 0)
                {
                    Trace.WriteLine("SafetyHashTable: Readers waiting");        
                    Monitor.PulseAll(Hash);
                }
                else
                {
                    Trace.WriteLine("SafetyHashTable: Without readers waiting");        
                    Monitor.Pulse(Hash);
                }
                Trace.WriteLine("SafetyHashTable: Exclusive Access Released");        
            }
        }

        public void ReleaseShared()
        {
            lock (Hash)
            {
                AcessCount--;
                if (AcessCount == 0)
                {
                    Monitor.Pulse(Hash);
                }
            }
        }
    }   
}